package com.lotso.web.module.system.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.lotso.web.common.ReqParam;
import com.lotso.web.common.Result;
import com.lotso.web.common.exception.BusinessException;
import com.lotso.web.common.exception.ParameterException;
import com.lotso.web.module.system.entity.Role;
import com.lotso.web.module.system.entity.User;
import com.lotso.web.module.system.entity.UserRole;
import com.lotso.web.module.system.mapper.IUserMapper;
import com.lotso.web.module.system.mapper.IUserRoleMapper;
import com.lotso.web.module.system.service.IUserService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * ClassName: UserServiceImpl
 * Description: 用户业务
 * Date: 2018/9/2 9:16 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<IUserMapper, User> implements IUserService {

    @Resource
    private IUserMapper userMapper;
    @Resource
    private IUserRoleMapper userRoleMapper;
    @Resource
    private PasswordEncoder encoder;

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public User getByUsername(String username) {
        User user = new User();
        user.setUsername(username);
        return userMapper.selectOne(user);
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public User getDetailByUsername(String username) {
        return userMapper.getDetailByUsername(username);
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public Result<User> list(ReqParam reqParam) {
        Page<User> userPage = new Page<>(reqParam.getPage(), reqParam.getLimit());
        List<User> userList = userMapper.listByPage(userPage, reqParam);
        return new Result<>(userPage.getTotal(), userList);
    }

    @Override
    public boolean add(User user) throws BusinessException {
        if (userMapper.selectOne(user) != null) {
            throw new BusinessException("账号已经存在");
        }
        // 新增用户，设置默认密码
        user.setPassword(this.encoderPwd(User.DEFAULT_PWD));
        boolean rs = userMapper.insert(user) > 0;
        if (rs) {
            List<String> roleIds = user.getRoles().stream().map(Role::getId).collect(Collectors.toList());
            if (userRoleMapper.insertBatch(user.getId(), roleIds) < roleIds.size()) {
                throw new BusinessException("添加失败，请重试");
            }
        }
        return rs;
    }

    @Override
    public boolean update(User user) {
        // 默认有值就更新。建议置空，防止数据注入
        user.setUsername(null);
        boolean rs = userMapper.updateById(user) > 0;
        if (rs) {
            // 角色处理：全删，全增
            userRoleMapper.delete(new EntityWrapper<UserRole>().eq("userId", user.getId()));
            List<String> roleIds = user.getRoles().stream().map(Role::getId).collect(Collectors.toList());
            if (userRoleMapper.insertBatch(user.getId(), roleIds) < roleIds.size()) {
                throw new BusinessException("修改失败，请重试");
            }
        }
        return rs;
    }

    @Override
    public boolean updateState(String userId, int state) throws ParameterException {
        if (state != User.NORMAL_STATE && state != User.NOT_NORMAL_STATE) {
            throw new ParameterException("state值需要在[0,1]中");
        }
        User user = new User();
        user.setId(userId);
        user.setState(state);
        return userMapper.updateById(user) > 0;
    }

    @Override
    public boolean updatePwd(String userId, String password) {

        User user = userMapper.selectById(userId);
        if (Objects.isNull(user)) {
            throw new BusinessException("用户不存在，请重试");
        }

        String username = user.getUsername();
        if (Objects.equals(User.ADMIN, username) || Objects.equals(User.SUPER_ADMIN, username)) {
            throw new BusinessException("超级管理员不能修改|重置密码");
        }

        user = new User();
        user.setId(userId);
        user.setPassword(this.encoderPwd(password));
        return userMapper.updateById(user) > 0;
    }

    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public User getById(String userId) {
        return userMapper.selectById(userId);
    }

    @Override
    public boolean delete(String userId) {

        User user = userMapper.selectById(userId);
        if (Objects.isNull(user)) {
            throw new BusinessException("用户不存在，请重试");
        }

        String username = user.getUsername();
        if (Objects.equals(User.ADMIN, username) || Objects.equals(User.SUPER_ADMIN, username)) {
            throw new BusinessException("超级管理员不能删除");
        }

        boolean res = userMapper.deleteById(userId) > 0;
        // 用户已经配置的角色需要删除
        if (res) {
            if (userRoleMapper.delete(new EntityWrapper<UserRole>().eq("userId", user.getId())) < 0) {
                throw new BusinessException("删除用户已分配角色失败，请重试");
            }
        }
        return res;
    }

    /**
     * 密码加密
     *
     * @param pwd
     * @return
     */
    private String encoderPwd(String pwd) {
        pwd = Strings.isNullOrEmpty(pwd) ? User.DEFAULT_PWD : pwd;
        return encoder.encode(pwd);
    }
}
